/* -*- P4_16 -*- */
#include <core.p4>
#include <v1model.p4>

/****************************** 常量定义 ******************************/
// 协议类型
const bit<16> ETHERTYPE_IPV4 = 0x800;
const bit<16> ETHERTYPE_ARP  = 0x0806;

// ARP相关常量
const bit<16> ARP_HARDWARE_ETHERNET = 0x0001;
const bit<16> ARP_PROTOCOL_IPV4    = 0x0800;
const bit<8>  ARP_HLEN_ETHERNET     = 6;
const bit<8>  ARP_PLEN_IPV4         = 4;
const bit<16> ARP_OP_REQUEST        = 1;
const bit<16> ARP_OP_REPLY          = 2;

/****************************** 类型定义 ******************************/
typedef bit<9>  PortId;        // 端口号类型（9位足够表示512个端口）
typedef bit<48> MacAddress;    // MAC地址类型
typedef bit<32> Ip4Address;    // IPv4地址类型

/****************************** 头部定义 ******************************/
// 以太网头部
header EthernetHeader {
    MacAddress dstMac;
    MacAddress srcMac;
    bit<16>    etherType;
}

// IPv4头部（完整字段版本）
header Ipv4Header {
    bit<4>    version: 4;        // 版本号（4位）
    bit<4>    ihl: 4;            // 头部长度（4位，以4字节为单位）
    bit<8>    diffServ;          // 差分服务
    bit<16>   totalLen;          // 总长度
    bit<16>   identification;    // 标识
    bit<3>    flags: 3;          // 分片标志（3位）
    bit<13>   fragOffset: 13;    // 分片偏移（13位）
    bit<8>    ttl;               // 生存时间
    bit<8>    protocol;          // 上层协议
    bit<16>   hdrChecksum;       // 头部校验和
    Ip4Address srcIp;            // 源IP
    Ip4Address dstIp;            // 目的IP
}

// ARP头部
header ArpHeader {
    bit<16>   hardwareType;      // 硬件类型
    bit<16>   protocolType;      // 协议类型
    bit<8>    hardwareLen;       // 硬件地址长度
    bit<8>    protocolLen;       // 协议地址长度
    bit<16>   operation;         // 操作类型
    MacAddress senderMac;        // 发送方MAC
    Ip4Address senderIp;         // 发送方IP
    MacAddress targetMac;        // 目标MAC（请求时为0）
    Ip4Address targetIp;         // 目标IP
}

/****************************** 元数据定义 ******************************/
struct Metadata {
    Ip4Address arpTargetIp;  // 存储ARP目标IP
}

// 组合头部结构体
struct PacketHeaders {
    EthernetHeader  eth;
    Ipv4Header      ipv4;
    ArpHeader       arp;
}

/****************************** 解析器 ******************************/
parser PacketParser(
    packet_in  packet,
    out       PacketHeaders hdr,
    inout     Metadata meta,
    inout     standard_metadata_t stdMeta
) {
    state start {
        transition parseEthernet();  // 初始状态：解析以太网头部
    }

    state parseEthernet() {
        packet.extract(hdr.eth);  // 提取以太网头部
        
        // 根据协议类型选择后续解析路径
        switch (hdr.eth.etherType) {
            case ETHERTYPE_IPV4:
                transition parseIpv4();
            case ETHERTYPE_ARP:
                transition parseArp();
            default:
                transition accept();
        }
    }

    state parseIpv4() {
        packet.extract(hdr.ipv4);  // 提取IPv4头部
        transition accept();
    }

    state parseArp() {
        packet.extract(hdr.arp);       // 提取ARP头部
        meta.arpTargetIp = hdr.arp.targetIp;  // 保存目标IP到元数据
        transition accept();
    }
}

/****************************** 校验和验证 ******************************/
control ChecksumValidator {
    apply {
        // 此处可添加实际校验和验证逻辑（示例中暂空）
    }
}

/****************************** 入口控制逻辑 ******************************/
control IngressPipeline {
    // 动作定义
    action DropPacket() {
        mark_to_drop(standard_metadata);  // 标记丢弃数据包
    }

    action ForwardIpv4(PortId port, MacAddress dstMac) {
        // 设置出口端口
        standard_metadata.egress_spec = port;
        
        // 更新以太网头部（源MAC为交换机MAC，需实际配置）
        hdr.eth.srcMac = MySwitchMac;  // 假设MySwitchMac为交换机MAC常量
        hdr.eth.dstMac = dstMac;
        
        // 处理IPv4头部
        hdr.ipv4.ttl = hdr.ipv4.ttl - 1;  // TTL递减
        hdr.arp.setInvalid();             // 清除可能存在的ARP头部
    }

    action ReplyArp(MacAddress switchMac, Ip4Address switchIp) {
        // 构造ARP响应包
        hdr.eth.dstMac = hdr.arp.senderMac;  // 目标MAC为请求方MAC
        hdr.eth.srcMac = switchMac;           // 源MAC为交换机MAC
        
        hdr.arp.operation = ARP_OP_REPLY;      // 设置为响应操作
        hdr.arp.senderMac = switchMac;
        hdr.arp.senderIp = switchIp;
        hdr.arp.targetMac = hdr.arp.senderMac; // 目标MAC/IP交换为请求方信息
        hdr.arp.targetIp = hdr.arp.senderIp;
        
        // 从入口端口返回响应
        standard_metadata.egress_spec = standard_metadata.ingress_port;
        
        // 清除可能存在的IPv4头部
        hdr.ipv4.setInvalid();
    }

    // 表定义
    table Ipv4RoutingTable {
        key = {
            hdr.ipv4.dstIp: lpm;  // 最长前缀匹配目标IP
        }
        actions = {
            ForwardIpv4;
            DropPacket;
            NoAction;
        }
        size = 2048;           // 增大路由表容量
        default_action = NoAction();
    }

    table ArpProcessingTable {
        key = {
            hdr.arp.operation: exact;  // 精确匹配操作类型（请求/响应）
            hdr.arp.targetIp: lpm;     // 匹配目标IP
        }
        actions = {
            ReplyArp;
            DropPacket;
        }
        size = 1024;
        default_action = DropPacket();
    }

    apply {
        // 根据协议类型分流处理
        if (hdr.eth.etherType == ETHERTYPE_IPV4) {
            Ipv4RoutingTable.apply();  // 处理IPv4包
        } else if (hdr.eth.etherType == ETHERTYPE_ARP) {
            ArpProcessingTable.apply();  // 处理ARP包
        }
    }
}

/****************************** 出口控制逻辑 ******************************/
control EgressPipeline {
    apply {
        // 可扩展QoS、流量统计等功能
    }
}

/****************************** 校验和计算 ******************************/
control ChecksumCalculator {
    apply {
        // 仅当IPv4头部有效时更新校验和
        if (hdr.ipv4.isValid()) {
            update_checksum(
                true,
                { hdr.ipv4.version, hdr.ipv4.ihl, hdr.ipv4.diffServ,
                  hdr.ipv4.totalLen, hdr.ipv4.identification, hdr.ipv4.flags,
                  hdr.ipv4.fragOffset, hdr.ipv4.ttl, hdr.ipv4.protocol,
                  hdr.ipv4.srcIp, hdr.ipv4.dstIp },
                hdr.ipv4.hdrChecksum,
                HashAlgorithm.csum16
            );
        }
    }
}

/****************************** 反解析器 ******************************/
control PacketDeparser {
    apply {
        packet.emit(hdr.eth);          // 先发送以太网头部
        if (hdr.ipv4.isValid()) {       // 若有有效IPv4头部，发送之
            packet.emit(hdr.ipv4);
        }
        if (hdr.arp.isValid()) {        // 若有有效ARP头部，发送之
            packet.emit(hdr.arp);
        }
    }
}

/****************************** 主程序定义 ******************************/
V1Switch(
    PacketParser(),
    ChecksumValidator(),
    IngressPipeline(),
    EgressPipeline(),
    ChecksumCalculator(),
    PacketDeparser()
) main;